package com.example.android.wifidirect.discovery;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener;
import android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener;
import android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

public class WiFiServiceDiscoveryActivity extends Activity implements
		Handler.Callback, ConnectionInfoListener, PeerListListener {

	public static final String TAG = "wifidirectdemo";

	// TXT RECORD properties
	public static final String TXTRECORD_PROP_AVAILABLE = "available";
	public static final String SERVICE_INSTANCE = "_wifidemotest";
	public static final String SERVICE_REG_TYPE = "_presence._tcp";

	public static final int MESSAGE_READ = 0x400 + 1;
	public static final int MY_HANDLE = 0x400 + 2;
	private WifiP2pManager manager;

	static final int SERVER_PORT = 4545;

	private final IntentFilter intentFilter = new IntentFilter();
	private Channel channel;
    private BroadcastReceiver receiver = null;

	private WifiP2pDnsSdServiceRequest serviceRequest;

	private Handler handler = new Handler(this);


	private int sampleNumber;
	
	private TextView statusTxtView;

	public Handler getHandler() {
		return handler;
	}

	public void setHandler(Handler handler) {
		this.handler = handler;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
		intentFilter
				.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
		intentFilter
				.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

		manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
		channel = manager.initialize(this, getMainLooper(), null);
		startRegistrationAndDiscovery();

		statusTxtView = (TextView) findViewById(R.id.textView1);
		
		new Timer().schedule(new PeersTimerTask(), 0, 1 * 60 * 1000);
	}

	@Override
	protected void onRestart() {
		super.onRestart();
	}

	@Override
	protected void onStop() {
		if (manager != null && channel != null) {
			manager.removeGroup(channel, new ActionListener() {

				@Override
				public void onFailure(int reasonCode) {
					Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
				}

				@Override
				public void onSuccess() {
				}

			});
		}
		super.onStop();
	}

	/**
	 * Registers a local service and then initiates a service discovery
	 */
	private void startRegistrationAndDiscovery() {
		Map<String, String> record = new HashMap<String, String>();
		record.put(TXTRECORD_PROP_AVAILABLE, "visible");

		WifiP2pDnsSdServiceInfo service = WifiP2pDnsSdServiceInfo.newInstance(
				SERVICE_INSTANCE, SERVICE_REG_TYPE, record);
		manager.addLocalService(channel, service, new ActionListener() {

			@Override
			public void onSuccess() {
				appendStatus("Added Local Service");
			}

			@Override
			public void onFailure(int error) {
				appendStatus("Failed to add a service");
			}
		});

		discoverService();
	}

	private void discoverService() {

		manager.setDnsSdResponseListeners(channel,
				new DnsSdServiceResponseListener() {

					@Override
					public void onDnsSdServiceAvailable(String instanceName,
							String registrationType, WifiP2pDevice srcDevice) {

					}
				}, new DnsSdTxtRecordListener() {

					/**
					 * A new TXT record is available. Pick up the advertised
					 * buddy name.
					 */
					@Override
					public void onDnsSdTxtRecordAvailable(
							String fullDomainName, Map<String, String> record,
							WifiP2pDevice device) {
						Log.d(TAG,
								device.deviceName + " is "
										+ record.get(TXTRECORD_PROP_AVAILABLE));

					}
				});
		

		// After attaching listeners, create a service request and initiate
		// discovery.
		serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
		manager.addServiceRequest(channel, serviceRequest,
				new ActionListener() {

					@Override
					public void onSuccess() {
						appendStatus("Added service discovery request");
					}

					@Override
					public void onFailure(int arg0) {
						appendStatus("Failed adding service discovery request");
					}
				});

		manager.discoverServices(channel, new ActionListener() {

			@Override
			public void onSuccess() {
				appendStatus("Service discovery initiated");
			}

			@Override
			public void onFailure(int arg0) {
				appendStatus("Service discovery failed");

			}
		});

	}

	@Override
	public boolean handleMessage(Message msg) {
		return true;
	}

	@Override
	public void onResume() {
	       super.onResume();
	        receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
	        registerReceiver(receiver, intentFilter);
	}

	@Override
	public void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
	}

	@Override
	public void onConnectionInfoAvailable(WifiP2pInfo p2pInfo) {
	}

	public void appendStatus(String status) {
		statusTxtView.setLines(10);
		statusTxtView.setText(status);

	}

	@Override
	public void onPeersAvailable(WifiP2pDeviceList peers) {
		if (peers == null) {
			return;
		}

		Collection<WifiP2pDevice> peerList = peers.getDeviceList();
		String names = "Current: " + sampleNumber + " ";
		sampleNumber++;

		for (WifiP2pDevice someone : peerList) {
			names += someone.deviceName + "\n ";
		}

		appendStatus(names);
	}

	class PeersTimerTask extends TimerTask {

		@Override
		public void run() {
			manager.stopPeerDiscovery(channel, new ActionListener() {

				@Override
				public void onSuccess() {
					manager.discoverServices(channel, new ActionListener() {

						@Override
						public void onSuccess() {
							appendStatus("Timer: Service discovery initiated");
						}

						@Override
						public void onFailure(int arg0) {
							appendStatus("Timer: Service discovery failed");

						}
					});

				}

				@Override
				public void onFailure(int arg0) {
					appendStatus("Timer: Service discovery failed");

				}
			});

			manager.requestPeers(channel, WiFiServiceDiscoveryActivity.this);
		}
	}
}
